import { ConfigProvider } from "antd";
import { ThemeConfig } from "antd/lib/config-provider/context";
import { createContext, Dispatch, FC, PropsWithChildren, SetStateAction, useEffect, useMemo, useRef, useState } from "react";
import { getUserInfo as getUserInfoApi } from "src/api";
import { AdminRecord } from "src/views/admin/AdminType";
import { useLocalStorage } from "../hooks";
import zhCN from "antd/es/locale/zh_CN";
import useWebSocket, { ReadyState } from "react-use-websocket";
import { JsonPrimitive, JsonValue, SendJsonMessage, WebSocketLike } from "react-use-websocket/dist/lib/types";
import { BaseResponse, toast } from "src/util";
import { Provider } from "react-redux";
import { store } from "@/store";
import { Menu, Item, useContextMenu, TriggerEvent } from "react-contexify";

export interface ContextMenuItem {
	onClick: () => void;
	text: string;
}
export type ReceivedMessage = { adminId: string; linkId: string; content: string; type: 1 | 2; avatar: string; timeStamp?: number };
type CurrentMessage = (BaseResponse<string | ReceivedMessage> & { type: string }) | null;
export interface AppContextProps {
	auth: string | null;
	setAuth: Dispatch<SetStateAction<string | null>>;
	removeAuth: () => null;
	themeCongifg: ThemeConfig;
	setThemeConfig: Dispatch<SetStateAction<ThemeConfig>>;
	REACT_APP_BASEURL: string;
	userInfo: AdminRecord | null;
	getUserInfo: () => Promise<AdminRecord | null>;
	sendJsonMessage: SendJsonMessage;
	currentMessage: CurrentMessage;
	receivedMessage: ReceivedMessage | ReceivedMessage[] | null;
	webSocketReadyState: ReadyState;
	getWebSocket: () => WebSocketLike | null;
	showContextMenu: (list: ContextMenuItem[], event: TriggerEvent) => void;
}

const defaultThemeConfig: ThemeConfig = {
	token: {
		colorPrimary: "#3C89FF",
	},
};

export const AppContext = createContext<AppContextProps>({
	auth: null,
	setAuth: () => null,
	removeAuth: () => null,
	themeCongifg: defaultThemeConfig,
	setThemeConfig: () => null,
	REACT_APP_BASEURL: process.env.REACT_APP_BASEURL || "",
	userInfo: null,
	getUserInfo: async () => null,
	sendJsonMessage: () => null,
	currentMessage: null,
	receivedMessage: null,
	webSocketReadyState: ReadyState["UNINSTANTIATED"],
	getWebSocket: () => null,
	showContextMenu: () => null,
});

const AppProviderWrapper: FC<PropsWithChildren> = ({ children }) => {
	const [themeCongifg, setThemeConfig] = useLocalStorage<ThemeConfig>("themeConfig");
	const [auth, setAuth, removeAuth] = useLocalStorage("Authorization");
	const [userInfo, setUserInfo] = useState<AdminRecord | null>(null);
	const getUserInfo = async () => {
		const userInfo = await getUserInfoApi();
		setUserInfo(userInfo.data);
		return userInfo.data;
	};
	const didUnmount = useRef(false);
	const {
		sendJsonMessage,
		lastMessage,
		readyState: webSocketReadyState,
		getWebSocket,
	} = useWebSocket(process.env.REACT_APP_SOCKET || "", {
		shouldReconnect: () => {
			return didUnmount.current === false;
		},
		// onMessage(ev) {
		// 	console.log(ev);
		// },
		reconnectAttempts: 10,
		reconnectInterval: 3000,
	});
	const send = (eventName: string, content: JsonValue | JsonPrimitive) => {
		sendJsonMessage({ event: eventName, data: content });
	};
	const currentMessage = useMemo<CurrentMessage>(() => {
		if (!lastMessage) return null;
		try {
			const result = JSON.parse(lastMessage?.data);
			if (result.code === 200) {
				return result;
			} else {
				result.message && toast.error(result.message);
				return null;
			}
		} catch (error) {
			console.log({ error });
			return null;
		}
	}, [lastMessage]);

	const receivedMessage = useMemo(() => {
		if (currentMessage && currentMessage.type === "message") {
			if (typeof currentMessage.data !== "string") {
				return currentMessage.data || null;
			} else {
				return null;
			}
		}
		return null;
	}, [currentMessage]);

	useEffect(() => {
		if (webSocketReadyState === 1 && auth) {
			send("joinClients", { auth });
		}
	}, [webSocketReadyState, auth]);
	useEffect(() => {
		return () => {
			didUnmount.current = true;
		};
	}, []);
	useEffect(() => {
		!themeCongifg && setThemeConfig(defaultThemeConfig);
	}, [themeCongifg]);

	const { show } = useContextMenu({
		id: "AppContextMenu",
	});
	const [menuList, setMenuList] = useState<ContextMenuItem[]>([]);
	const showContextMenu = (list: ContextMenuItem[], event: TriggerEvent) => {
		setMenuList(list);
		show({ event });
	};
	return (
		<Provider store={store}>
			<ConfigProvider locale={zhCN} theme={themeCongifg as ThemeConfig}>
				<AppContext.Provider
					value={{
						auth,
						setAuth,
						removeAuth,
						themeCongifg: themeCongifg as ThemeConfig,
						setThemeConfig: setThemeConfig as Dispatch<SetStateAction<ThemeConfig>>,
						REACT_APP_BASEURL: process.env.REACT_APP_BASEURL || "",
						userInfo,
						getUserInfo,
						sendJsonMessage,
						currentMessage,
						receivedMessage,
						webSocketReadyState,
						getWebSocket,
						showContextMenu,
					}}
				>
					{children}
					<Menu id="AppContextMenu" style={{ zIndex: 2000 }}>
						{menuList.map((item, index) => (
							<Item key={index} onClick={item.onClick}>
								{item.text}
							</Item>
						))}
					</Menu>
				</AppContext.Provider>
			</ConfigProvider>
		</Provider>
	);
};

export default AppProviderWrapper;
